<script setup>
import {ref} from "vue";
import mqtt from "mqtt";
// 消息质量取值数组
const qosList = [0, 1, 2];

const connectionInfo = ref({
  protocol: 'ws',
  host: "110.42.101.19",
  port: 8083,
  clientId: "emqx_vue3_" + Math.random().toString(16).substring(2, 8),
  username: "zhangsan",
  password: "123",
  clean: true,
  connectTimeout: 10 * 1000, // ms
  reconnectPeriod: 4000, // ms
})
const client = ref({})
const clientInitData = ref({      // 链接初始化相关数据
  connnected: false
})
const createConnection = () => {

  const { protocol, host, port , ...options } = connectionInfo.value;
  const connectUrl = `${protocol}://${host}:${port}/mqtt`;
  console.log(connectUrl)
  client.value = mqtt.connect(connectUrl , options);   // 建立连接
  clientInitData.value.connnected = true ;
  console.info("创建连接成功...")

}
const closeConnection = () => {

  // 关闭链接
  client.value.end(false , () => {   // 如果设置为true，将会立即关闭套接字，并且不发送MQTT DISCONNECT包。如果设置为false（默认值），则会发送MQTT DISCONNECT包给代理，然后关闭套接字。
    clientInitData.value.connnected = false;
    console.info("关闭连接成功...")
  })

}

const receivedMessages = ref({})
const subscriptionInfo = ref({     // 订阅参数数据模型
  topic: '' ,
  qos: 0
})

const subscriptionInitData = ref({	// 订阅初始化数据
  subscription: false
})
const subscriptionTopicHandler = () => {

  const { topic, qos } = subscriptionInfo.value
  console.info("qos:",qos);
  console.info("topic:",topic);
  console.info("client.value:",client.value);
  client.value.subscribe(topic, { qos } , (error , res) => {
    if(error) {
      console.info("主题订阅失败了:", error);
      return ;
    }
    subscriptionInitData.value.subscription = true ;
    console.info("主题订阅成功.... ");

    // 订阅成功以后，监听发送消息事件
    client.value.on('message' , (topic , message) => {
      console.info("topic -----> " + topic + ", message -----> " + message)
      receivedMessages.value = "topic -----> " + topic + ", message -----> " + message ;
    })

  })

}

const unSubscriptionTopicHandler = () => {
  const {topic, qos } = subscriptionInfo.value
  client.value.unsubscribe(topic, { qos } , (error , res) => {
    if(error) {
      console.info("取消订阅失败:", error);
      return ;
    }
    subscriptionInitData.value.subscription = false ;
    console.info("取消订阅成功.... ");

  })
}

const publishInfo = ref({
  topic: '' ,
  qos: 0,
  payLoad: ''
})

const doPublish = () => {
  const {topic , payLoad , qos } = publishInfo.value ;
  client.value.publish(topic , payLoad , { qos } , (error , res) => {
    if(error) {
      console.info("发送消息失败...." , error)
      return ;
    }
    console.info("发送消息成功....")
  }) ;

}
</script>

<template>
  <div class="mqtt-demo">
    <el-card>
      <h1>配置信息</h1>
      <el-form label-position="top" >
        <el-row :gutter="20">

          <el-col :span="8">
            <el-form-item prop="protocol" label="选择协议">
              <el-select v-model="connectionInfo.protocol">
                <el-option label="ws://" value="ws"></el-option>
                <el-option label="wss://" value="wss"></el-option>
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="8">
            <el-form-item prop="host" label="主机地址">
              <el-input v-model="connectionInfo.host" ></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="8">
            <el-form-item prop="port" label="端口号">
              <el-input type="number" v-model="connectionInfo.port" placeholder="8083/8084"></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="8">
            <el-form-item prop="clientId" label="客户端ID">
              <el-input v-model="connectionInfo.clientId"> </el-input>
            </el-form-item>
          </el-col>


          <el-col :span="8">
            <el-form-item prop="username" label="用户名">
              <el-input v-model="connectionInfo.username"></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="8">
            <el-form-item prop="password" label="密码">
              <el-input v-model="connectionInfo.password"></el-input>
            </el-form-item>
          </el-col>

          <el-col :span="24">
            <el-button type="primary" :disabled="clientInitData.connnected" @click="createConnection">建立连接</el-button>
            <el-button type="danger" :disabled="!clientInitData.connnected" @click="closeConnection">断开连接</el-button>
          </el-col>

        </el-row>
      </el-form>
    </el-card>


    <el-card>
      <h1>订阅主题</h1>
      <el-form label-position="top" >
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item prop="topic" label="Topic">
              <el-input v-model="subscriptionInfo.topic"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="qos" label="QoS">
              <el-select v-model="subscriptionInfo.qos">
                <el-option
                    v-for="qos in qosList"
                    :key="qos"
                    :label="qos"
                    :value="qos"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-button  type="primary" class="sub-btn" :disabled="subscriptionInitData.subscription" @click="subscriptionTopicHandler">订阅主题</el-button>
            <el-button type="primary" class="sub-btn" :disabled="!subscriptionInitData.subscription" @click="unSubscriptionTopicHandler">取消订阅</el-button>
          </el-col>
        </el-row>
      </el-form>
    </el-card>

    <el-card>
      <h1>发布消息</h1>
      <el-form label-position="top" >
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item prop="topic" label="Topic">
              <el-input v-model="publishInfo.topic"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="payload" label="Payload">
              <el-input v-model="publishInfo.payLoad"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="qos" label="QoS">
              <el-select v-model="publishInfo.qos">
                <el-option
                    v-for="qos in qosList"
                    :key="qos"
                    :label="qos"
                    :value="qos"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <el-col :span="24" class="text-right">
        <el-button type="primary" @click="doPublish">发布消息</el-button>
      </el-col>
    </el-card>

    <el-card>
      <h1>接收到的消息</h1>
      <el-col :span="24">
        <el-input
            type="textarea" v-model="receivedMessages"
            :rows="3"
            readonly
        ></el-input>
      </el-col>
    </el-card>
  </div>
</template>

<style>
.mqtt-demo {
  max-width: 1200px;
  margin: 32px auto 0 auto;
}

h1 {
  font-size: 16px;
  margin-top: 0;
}

.el-card {
  margin-bottom: 32px;
}
.el-card__body {
  padding: 24px;
}

.el-select {
  width: 100%;
}

.text-right {
  text-align: right;
}

.sub-btn {
  margin-top: 30px;
}
</style>
